package com.example.io;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class ClientDemo {
    public static void main(String[] args) throws Exception {
        // demo1();
        // demo1_1();

        // 模拟 多个 client 连接 server
        new Thread(() -> {
            try {
                demo1();
                demo1();
                demo1();
                demo1();
                demo1();
            } catch (Exception e) { }
        }).start();

        demo2(); // 这个方法会阻塞主线程
    }

    /**
     * 只收发一次：
     *  客户端程序关闭
     *  服务端报错
     *      Exception in thread "main" java.net.SocketException: Connection reset
     */
    public static void demo1() throws Exception {
        System.out.println("==客户端的启动==");
        // （1）创建一个Socket的通信管道，请求与服务端的端口连接。
        Socket socket = new Socket("127.0.0.1",8888);
        // （2）从Socket通信管道中得到一个字节输出流。
        OutputStream os = socket.getOutputStream();
        // （3）把字节流改装成自己需要的流进行数据的发送
        PrintStream ps = new PrintStream(os);
        // （4）开始发送消息
        ps.println("我是客户端，我想约你吃小龙虾！！！");
        ps.flush();
    }

    /**
     * 客户端可多次发送
     * 服务器可多次接收
     */
    public static void demo1_1() throws Exception {
        System.out.println("==客户端的启动==");
        // （1）创建一个Socket的通信管道，请求与服务端的端口连接。
        Socket socket = new Socket("127.0.0.1",8888);
        // （2）从Socket通信管道中得到一个字节输出流。
        OutputStream os = socket.getOutputStream();
        // （3）把字节流改装成自己需要的流进行数据的发送
        PrintStream ps = new PrintStream(os);
        // （4）开始发送消息
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            ps.println(sc.nextLine());
            ps.flush();
        }
    }

    /**
     * 多次交互，一应一答
     */
    public static void demo2() throws Exception {
        System.out.println("==客户端的启动==");
        // （1）创建一个Socket的通信管道，请求与服务端的端口连接。
        Socket socket = new Socket("127.0.0.1",8888);
        // （2）从Socket通信管道中得到一个字节输出流。
        OutputStream os = socket.getOutputStream();
        // （3）把字节流改装成自己需要的流进行数据的发送
        PrintStream ps = new PrintStream(os);

        // 新起一个线程，单独处理收到的消息
        new Thread(() -> {
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String line = "";
                while ((line = br.readLine()) != null) {
                    System.out.println("from server: " + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // （4）开始发送消息
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String s = sc.nextLine();
            if (null == s || "".equals(s))
                continue;
            ps.println(s);
            ps.flush();
        }
    }

}